基本介绍
当需要找出问题的解集,或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。
回溯法的基本做法是搜索,或是一种组织得井井有条的,能避免不必要搜索
的穷举式搜索法。
在问题的解空间树中,回溯法按深度优先策略
,从根结点出发搜索解空间树。
基本思想
- 扩展结点:一个正在产生儿子的结点
- 活结点:一个自身已生成但其儿子还没有全部生成的节点
- 死结点:一个所有儿子已经产生的结点
- 确定了解空间的组织结构后,回溯法从开始节点出发,
以深度优先方式
搜索整个解空间,这个开始节点成为活节点
,同时成为当前的扩展结点
。 - 在当前的可扩展结点处,搜索向纵深方向移至一个新的结点,这个新结点成为
当前的活结点
,并成为扩展结点
。 - 如果在当前的可扩展结点处不能向纵深方向移动(
结点不包含问题解、没有可扩展的结点、到达叶子结点
),则当前扩展结点变成死结点。此时,应回溯至最近的一个活动结点处,并使这个活动结点成为当前的扩展结点。 - 回溯法以这种工作方式递归地在解空间中搜索,直至找到所要求的解或者解空间中
已无活动结点为止
。
0-1背包举例
这里仅仅是将0-1背包问题的子集树列出来进行展示一下。具体的问题分析请看 👉 0-1背包问题-回溯法
常用剪枝函数:
搜索左子树时:用约束函数
在扩展结点处剪去不满足约束的左子树;
搜索右子树时:用限界函数
剪去得不到最优解的右子树。
在上个例子中:
约束函数cw+wi ≥ C
时,剪掉左子树。即:cw+wi ≤ C时,搜索左子树
限(上)界函数cp+r ≤ Bestv 时
,剪掉右子树。即:cp+r > Bestv时,搜索右子树
解题步骤
- 针对所给问题,定义问题的解空间
- 确定易于搜索的解空间结构
- 以深度优先方式搜索解空间,并在搜索过程中用
剪枝函数
避免无效搜索
子集树与排列树
子集树
: 所给的问题是从n个元素的集合中找出满足某种性质的子集时, 相应的解空间称为子集树.
子集树通常有2n个叶结点, 遍历子集树的任何算法均需Ω(2n)的计算时间.
例如: 0-1背包问题的解空间为一棵子集树.
排列树
: 当所给的问题是确定n个元素满足某种性质的排列时, 相应的解空间称为排列树.
排列树通常有(n-1)!个叶结点, 遍历排列树需要Ω(n!)的计算时间.
例如: 旅行售货员问题的解空间为一棵排列树
.
旅行售货员问题
装载问题
👉 装载问题-回溯法